/**
 *
 */
package yl.hs.bmipfull.pojo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import yl.hs.bmipfull.utils.HanYuHelper;
import yl.hs.bmipfull.utils.Tl;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 谢景广 <br/>
 * 实体类基类
 */
public class BaseEntity{


    public void setParent(IParent parent) {
        if (this instanceof IParent) {
            var entity = (IParent) this;
            if (parent != null) {
                entity.setLayer(parent.getLayer() + 1);
                entity.setParentCode(parent.getParentCode() + ',' + entity.getSn());
            } else {
                entity.setLayer(0);
                entity.setParentCode(entity.getSn());
            }
        }
    }

    /**
     * 设置拼音字段值
     */
    public void setPYFieldValue() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        var classType = this.getClass();
        var methods = classType.getMethods();
        if (methods.length > 0) {
            for (var setmethod : methods) {
                var fname = setmethod.getName();
                if (fname.endsWith("PY") && fname.startsWith("set")) {
                    Object orgvalue = null;
                    var fieldName = fname.substring(3, fname.length() - 2);

                    for (var getmethod : methods) {

                        if (("get" + fieldName).equals(getmethod.getName())
                                || ("is" + fieldName).equals(getmethod.getName())) {
                            orgvalue = getmethod.invoke(this, new Object[]{});
                        }
                    }
                    if (orgvalue != null && orgvalue.toString() != "") {
                        var value = HanYuHelper.getShortSpec(orgvalue.toString());
                        setmethod.invoke(this, new Object[]{value});
                    }
                }
            }
        }
    }


    private List<Field> getClassFields(Class<?> cls){
        List<Field> list = new ArrayList<>();
        list.addAll(Arrays.stream(cls.getDeclaredFields()).toList());
        if(cls.getSuperclass() !=null){
            list.addAll(getClassFields(cls.getSuperclass()));
        }
        return list;
    }

    /**
     * 实体转映射
     *
     * @return Map结构实体类
     */
    public Map<String, Object> toMap() {
        Map<String, Object> map = new HashMap<>();
        var classType = this.getClass();
        var fields = getClassFields(classType);
        for (Field field :fields) {
            try {
                String fieldName = field.getName().replace("_", "");
                String firstLetter = fieldName.substring(0, 1).toUpperCase();
                var methodHead = "get";
                var ftype = field.getType();
                if (ftype.getName().toLowerCase(Locale.ROOT) == "boolean") {
                    if(fieldName.startsWith("is")){
                        methodHead = "";
                        firstLetter = firstLetter.toLowerCase(Locale.ROOT);
                    }
                    else {
                        methodHead = "is";
                    }
                }
                // 获得和属性对应的getXXX()方法的名字
                String getMethodName = methodHead + firstLetter + fieldName.substring(1);
                // 获得和属性对应的getXXX()方法
                Method getMethod = classType.getMethod(getMethodName, new Class[]{});
                // 调用原对象的getXXX()方法
                Object value = getMethod.invoke(this, new Object[]{});
                map.put(fieldName, value);
            } catch (Exception ee) {
                ee.printStackTrace();
            }
        }
        return map;
    }


    /**
     * 实体类转化为Json
     * @return Json类型字符串
     * @throws JsonProcessingException 转化失败异常
     * @see com.fasterxml.jackson.core.JsonProcessingException
     */
    public String toJson() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
        return objectMapper.writeValueAsString(this);
    }

    @JsonIgnore()
    public String getSNCode(){
        var filed = Tl.getSerialNoDBField(this.getClass());
        if(filed!=null){
            return filed.snPrefix();
        }
        return "SN";
    }
}
